package main

import "fmt"

//优先使用对象组合而不是类的继承

// type report struct {
// 	sol       int     //日期
// 	high, low float64 //最高温、最低温
// 	lat, long float64 //经纬度
// }

// type report struct {
// 	sol         int
// 	temperature temperature
// 	location    location
// }

//struct嵌入
//嵌入的struct中有一些方法,，可以直接为report的类型作用
//没有字段名，只有类型名，这时候直接使用类型名作为字段名即可调用
type report struct {
	sol
	temperature
	location
}

type temperature struct {
	high, low celsius
}

type location struct {
	lat, long float64
}

//摄氏度
type celsius float64

func (t temperature) average() celsius {
	return (t.high + t.low) / 2
}

type sol int

//方法的转发
// func (r report) average() celsius {
// 	return r.temperature.average()
// }

//命名冲突示例
func (s sol) days(s2 sol) int {
	days := int(s2 - s)
	if days < 0 {
		days = -days
	}
	return days
}

//命名冲突示例
func (l location) days(l2 location) int {
	return 5
}

func main() {
	bradbury := location{-4.6876, 137.342}
	t := temperature{high: -1.0, low: -78.0}
	fmt.Println(t.average())

	report := report{
		sol:         15,
		temperature: t,
		location:    bradbury,
	}

	fmt.Println(report.temperature.average())
	// fmt.Println(report.average())

	fmt.Println(report.temperature.high)
	fmt.Println(report.location.long)
	fmt.Printf("%+v\n", report)
	fmt.Printf("a balmy %v° C\n", report.temperature.high)

	//命名冲突示例
	//fmt.Println(report.days(report.sol)) //调用就会报错，不调用就没事

	//明确调用不会报错
	fmt.Println(report.sol.days(report.sol))

	//在声明接受者为report方法之后可以调用，且不报错
	fmt.Println(report.days(report.location))
}

//如果就想report.days()调用 必须声明一个接收者为report的方法，明确指向
//自身的方法要比转发的方法 优先级要高
func (r report) days(l location) int {
	return r.location.days(l)
}
